package net.library.clink.core;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;

/**
 * 输入和输出的参数类
 * 完成了对ByteBuffer的封装
 */

public class IoArgs {
    private int limit = 256;
    private ByteBuffer buffer = ByteBuffer.allocate(limit);


    /**
     * 从ReadableByteChannel数组中读取数据
     */
    public int readFrom(ReadableByteChannel channel) throws IOException {
        startWriting();
        int bytesProduced = 0;
        while (buffer.hasRemaining()) {
            int len = channel.read(buffer);
            if (len < 0) {
                throw new EOFException();
            }
            bytesProduced += len;
        }
        finishWriting();
        return bytesProduced;
    }

    /**
     * 向WritableByteChannel数据中写数据
     */
    public int writeTo(WritableByteChannel channel) throws IOException {
        int bytesProduced = 0;
        while (buffer.hasRemaining()) {
            int len = channel.write(buffer);
            if (len < 0) {
                throw new EOFException();
            }
            bytesProduced += len;
        }
        return bytesProduced;
    }

    /**
     * 从socketchannel中读取数据
     */
    public int readFrom(SocketChannel channel) throws IOException {
        startWriting();
        int bytesProduced = 0;
        while (buffer.hasRemaining()) {
            int len = channel.read(buffer);
            if (len < 0) {
                throw new EOFException();
            }
            bytesProduced += len;
        }
        finishWriting();
        return bytesProduced;
    }

    /**
     * 向socketchannel中写数据
     */
    public int writeTo(SocketChannel channel) throws IOException {
        int bytesProduced = 0;
        while (buffer.hasRemaining()) {
            int len = channel.write(buffer);
            if (len < 0) {
                throw new EOFException();
            }
            bytesProduced += len;
        }
        return bytesProduced;
    }

    /**
     * 开始写入数据到IoArgs之前的操作
     */
    public void startWriting() {
        buffer.clear();
        // 定义buffer的容纳区间
        buffer.limit(limit);
    }

    /**
     * 写完数据后调用，翻转buffer内数组的内容，以便读取数据
     */
    public void finishWriting() {
        buffer.flip();
    }

    /**
     * 设置单词写操作的容纳区间
     */
    public void limit(int limit) {
        this.limit = limit;
    }

    /**
     * 每次将buffer数据封装到Packet之前，先将数据的长度存到buffer头部
     * @param total
     */
    public void writeLength(int total) {
        startWriting();
        buffer.putInt(total);
        finishWriting();
    }

    /**
     * 每次得到的Packet解析成buffer后，前4个字节（int值）是数据的长度
     * @return
     */
    public int readLength() {
        return buffer.getInt();
    }

    public int capacity() {
        return buffer.capacity();
    }

    /**
     * IoArgs提供者、处理者;数据的产生或消费者
     */
    public interface IoArgsEventProcessor {
        /**
         * 提供一份可消费的IoArgs
         * @return
         */
       IoArgs providerIoArgs();

       void onConsumeCompleted(IoArgs args);

       void onConsumeFailed(IoArgs args, Exception e);
    }

    public interface IoArgsEventListener {
        void onStarted(IoArgs args);

        void onCompleted(IoArgs args);
    }

}
